#include <stdio.h>
#include "usart.h"

uint8_t nRx1Counter=0;                    //接收字节数
uint8_t USART_Rx1Buff[FRAME_BYTE_LENGTH]; //接收缓冲区
uint8_t USART_Rx1Data[FRAME_BYTE_LENGTH]; //接收数据区
uint8_t USART_Rx1FrameFlag = 0;           //接收完整数据帧标志，1完整，0不完整

void USART1_Init(void){
    
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 , ENABLE); //使能GPIOA和USART1时钟
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO ,ENABLE );
    
    GPIO_InitTypeDef GPIO_InitStructure;
    /* Configure USART1 Rx as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART1 Tx as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    
    USART_InitTypeDef USART_InitStructure;
    
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    /* Configure USARTy */
    USART_Init(USART1, &USART_InitStructure);

    /* Enable USARTy Receive and Transmit interrupts */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

    /* Enable the USARTy */
    USART_Cmd(USART1, ENABLE);
    
    
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Enable the USARTy Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
}


void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data){ 
	
    USART_SendData(USARTx, *Data);
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
}

void USART1_GetChar(uint8_t nChar) //串口接收到一个字节
{

	if(USART_Rx1FrameFlag == 1) return;   //如果上次的数据帧还没处理过，则返回
	
	if(nRx1Counter==0 && nChar == FRAME_START)
	{
		USART_Rx1Buff[nRx1Counter++]=nChar;  //保存到缓冲区
	}
	else if(nRx1Counter>0) //接收到帧头以后才继续保存
	{
		USART_Rx1Buff[nRx1Counter++]=nChar;  //保存到缓冲区
        
#if defined ENABLE_FRAME_CHECKSUM
        if(nRx1Counter==FRAME_BYTE_LENGTH-1){     //通讯校验
            uint16_t sum = 0;
            for(uint8_t i=1;i<nRx1Counter-1;i++)
                sum+=USART_Rx1Buff[i];
            if( (sum&0x00FF)!=USART_Rx1Buff[nRx1Counter-1] ){
                nRx1Counter = 0;                   //校验和不通过，重新接收
            }
        }
#endif
        
		if(nRx1Counter>=FRAME_BYTE_LENGTH)  //接收到一帧数据
		{
			nRx1Counter = 0;
			if(USART_Rx1Buff[FRAME_BYTE_LENGTH-1] == FRAME_END) //如果最后一个字节是帧尾，则数据帧完整
			{
                for(uint8_t i=0;i<FRAME_BYTE_LENGTH;i++)
                    USART_Rx1Data[i]=USART_Rx1Buff[i];
				USART_Rx1FrameFlag=1;
			}
		}
	}	
}


uint8_t USART1_Process(uint8_t info) //处理数据帧
{
    if(USART_Rx1FrameFlag != 1)return 0;
    
    
    
    USART_Rx1FrameFlag = 0;
    
    return 0;
    
}


/**
  * @brief  This function handles USART1 global interrupt request.
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
    uint8_t res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        /* Read one byte from the receive data register */
        res = USART_ReceiveData(USART1);   //将读寄存器的数据缓存到接收缓冲区里

        USART1_GetChar(res);

    }
  
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    {   
        /* Write one byte to the transmit data register */
        //USART_SendData(USART1, TxBuffer1[TxCounter1++]);

        //if(TxCounter1 == NbrOfDataToTransfer1)
        //{
          /* Disable the USARTy Transmit interrupt */
          USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
        //}    
    }
}

 
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE
{
	int handle;
 
};
FILE __stdout;
 
//重映射fputc函数，此函数为多个输出函数的基础函数
int fputc(int ch, FILE *f)
{
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
	USART_SendData(USART1, (uint8_t) ch);
	return ch;
}
